﻿@{
    ViewBag.Title = "Create2";
}

<script>
    var Point = function(x, y) {
        this.X = x;
        this.Y = y;
    }
    var TransformInfo = function(sourceOffset, targetOffset, baseScaleAmount) {
        this.sourceOffset = sourceOffset;
        this.targetOffset = targetOffset;
        this.baseScaleAmount = baseScaleAmount;

        this.getScaleTransform = function(scaleAmountX, scaleAmountY) {
            scaleAmountX = scaleAmountX == null ? 1 : scaleAmountX;
            scaleAmountY = scaleAmountY == null ? scaleAmountX : scaleAmountY;

            var transform = "translate(" + this.targetOffset.X + "," + this.targetOffset.Y + ")";
            transform += "scale(" + (this.baseScaleAmount * scaleAmountX) + "," + (this.baseScaleAmount * scaleAmountY) + ")";
            transform += "translate(" + (-this.sourceOffset.X) + "," + (-this.sourceOffset.Y) + ")";
            return transform;
        }
        this.getBaseTransform = function() {
            return this.getScaleTransform(1);
        }
    }

    var featureScaleInfo = {
        'MouthLowerExtent': null,
        'JawSliderValue': 50,
        'MouthPositionValue': 50,
        'MouthTranslateY': 0,
        'NoseTranslateY': 0,
        'NoseStretchAmount': 1,
        'NoseScaling': 1,
        'MouthStretchAmount': 1,
        'MouthScaling': 1,
        'JawScale': 1,
        'EyeTranslateY': 0,
        'EyeStretchAmount': 1,
        'EyeScaling': 1,
        'EyeDistanceOffset': 0,
        'EyeDisproportion': 1
    };

    var baseTransform = new Array();
    var slideFunctions = new Array();
    var downloadedFeatures = new Array();
    //TODO: this definition should come from the .NET code
    var selectedFeatures = {
        4: null,
        1: null,
        2: null,
        3: null,
    };

    //TODO: this definition should come from the .NET code
    var layerColors = {
        1: { Color: '#d28919', Opacity: 0 },
        2: { Color: '#d7c982', Opacity: 0 },
        3: { Color: '#000000', Opacity: 0 },
        6: { Color: '#000000', Opacity: 0.3 },
        9: { Color: '#000000', Opacity: 1 },
        10: { Color: '#000000', Opacity: 0.3 },
        11: { Color: '#000000', Opacity: 0.3 },
        12: { Color: '#000000', Opacity: 1 },
        13: { Color: '#000000', Opacity: 0.3 },
        14: { Color: '#000000', Opacity: 0 },
        15: { Color: '#ffffff', Opacity: 0 },
        16: { Color: '#ffffff', Opacity: 0 },
        19: { Color: '#000000', Opacity: 0 },
        21: { Color: '#d28919', Opacity: 0 },
        22: { Color: '#000000', Opacity: 0 },
        23: { Color: '#000000', Opacity: 0 },
        28: { Color: '#000000', Opacity: 1 },
        32: { Color: '#000000', Opacity: 0.3 },
        33: { Color: '#000000', Opacity: 0.3 },
        34: { Color: '#000000', Opacity: 0.3 },
        35: { Color: '#000000', Opacity: 0.3 },
        36: { Color: '#000000', Opacity: 0.3 },
        37: { Color: '#000000', Opacity: 0.3 },
    };

    function getFeature(featureId, onFeatureLoaded) {
        $.ajax({
            url: "../FaceDisplay/GetFeature?featureId=" + featureId,
            success: function (data) {
                downloadedFeatures[data.Id] = data;
                onFeatureLoaded(data);
            }
        });
    }

    function displayFeature(feature, targetElement) {
        var svgElement = $("<svg/>");
        var viewBoxText = feature.ViewBox.X + " " + feature.ViewBox.Y + " " + feature.ViewBox.Width + " " + feature.ViewBox.Height;
        svgElement.attr("viewBox", viewBoxText);

        for (var layerIndex in feature.Layers) {
            var layer = feature.Layers[layerIndex];
            var gElement = $("<g/>");
            svgElement.append(gElement);
            for (var pathIndex in layer.Pathes) {
                var path = layer.Pathes[pathIndex];
                var pathElement = $("<path/>");
                pathElement.attr("d", path);
                var color = layerColors[layer.Id] != null ? layerColors[layer.Id].Color : null;
                var opacity = layerColors[layer.Id] != null ? layerColors[layer.Id].Opacity : null;
                pathElement.attr("style", "fill:" + color + ";fill-opacity:" + opacity + ";");
                gElement.attr("layerTypeId", layer.Id);
                gElement.append(pathElement);
            }
        }

        targetElement.html(svgElement.get(0).outerHTML);

        slideFunctions['JawSlider'] = function (value) {
            featureScaleInfo.JawSliderValue = value;

            var topY;
            var marker = getMarkerPoint(selectedFeatures[4], 38);
            if (marker != null)
                topY = marker.Y;

            var yScale = value * 0.004 + 0.8;
            featureScaleInfo.JawScale = yScale;
            $("g[layerTypeId='28']").get(0).setAttribute("transform", "translate(0," + topY + ")scale(1," + yScale + ")translate(0," + (-topY) + ")");
            $("g[layerTypeId='32']").get(0).setAttribute("transform", "translate(0," + topY + ")scale(1," + yScale + ")translate(0," + (-topY) + ")");
            $("g[layerTypeId='34']").get(0).setAttribute("transform", "translate(0," + topY + ")scale(1," + yScale + ")translate(0," + (-topY) + ")");

            slideFunctions['MouthPosition'](featureScaleInfo.MouthPositionValue);
        };

        slideFunctions['EyeStretch'] = function(value) {
            featureScaleInfo.EyeStretchAmount = value * 0.016 + 0.2;
            updateEyeTransform();
        }

        slideFunctions['EyeScaling'] = function(value) {
            featureScaleInfo.EyeScaling = value * 0.016 + 0.2;
            updateEyeTransform();
        }

        slideFunctions['MouthScaling'] = function(value) {
            featureScaleInfo.MouthScaling = value * 0.016 + 0.2;
            updateMouthTransform();
        }

        slideFunctions['NoseScaling'] = function(value) {
            featureScaleInfo.NoseScaling = value * 0.016 + 0.2;
            updateNoseTransform();
        }

        slideFunctions['EyePosition'] = function(value) {
            var translateAmount = value - 50;
            featureScaleInfo.EyeTranslateY = translateAmount;
            updateEyeTransform();
        }

        slideFunctions['MouthStretch'] = function(value) {
            featureScaleInfo.MouthStretchAmount = value * 0.016 + 0.2;
            updateMouthTransform();
        }

        slideFunctions['NoseStretch'] = function(value) {
            featureScaleInfo.NoseStretchAmount = value * 0.016 + 0.2;
            updateNoseTransform();
        }

        slideFunctions['EyeDistance'] = function(value) {
            featureScaleInfo.EyeDistanceOffset = value - 50;
            updateEyeTransform();
        }

        slideFunctions['NosePosition'] = function(value) {
            var translateAmount = value - 50;
            featureScaleInfo.NoseTranslateY = translateAmount;
            updateNoseTransform();
        }

        slideFunctions['EyeDisproportion'] = function(value) {
            featureScaleInfo.EyeDisproportion = value * 0.016 + 0.2;
            updateEyeTransform();
        }

        slideFunctions['MouthPosition'] = function(value) {
            featureScaleInfo.MouthPositionValue = value;

            var lowerMouthExtent = getMarkerPoint(selectedFeatures[4], 40);
            var lowerLipBottom = getMarkerPoint(selectedFeatures[4], 35);
            var noseBottom = getMarkerPoint(selectedFeatures[4], 31);
            var upperLipTop = getMarkerPoint(selectedFeatures[4], 34);
            var translateAmount = 0;
            if (value >= 50) {
                var totalRange = lowerLipBottom.Y - lowerMouthExtent.Y;
                translateAmount = -totalRange * (value - 50) / 50;
            }
            else {
                var totalRange = noseBottom.Y - upperLipTop.Y;
                translateAmount = totalRange * (50 - value) / 50;
            }
            translateAmount = translateAmount * featureScaleInfo.JawScale - (noseBottom.Y - lowerMouthExtent.Y) * featureScaleInfo.JawScale + (noseBottom.Y - lowerMouthExtent.Y);
            featureScaleInfo.MouthTranslateY = translateAmount;

            updateMouthTransform();
        };

        $(".ValueSlider").slider({
            min:0,
            max:100,
            value:50,
            slide: function (event, ui) {
                slideFunctions[event.target.id](ui.value);
            }
        });
    }

    function updateNoseTransform() {
        $("g[layerTypeId='11']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.NoseTranslateY + ")" + baseTransform[11].getScaleTransform(featureScaleInfo.NoseScaling, featureScaleInfo.NoseScaling * featureScaleInfo.NoseStretchAmount));
        $("g[layerTypeId='12']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.NoseTranslateY + ")" + baseTransform[12].getScaleTransform(featureScaleInfo.NoseScaling, featureScaleInfo.NoseScaling * featureScaleInfo.NoseStretchAmount));
        //$("g[layerTypeId='13']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.NoseTranslateY + ")" + baseTransform[13].getScaleTransform(featureScaleInfo.NoseScaling, featureScaleInfo.NoseScaling * featureScaleInfo.NoseStretchAmount));
    }

    function updateMouthTransform() {
        $("g[layerTypeId='6']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.MouthTranslateY + ")" + baseTransform[6].getScaleTransform(featureScaleInfo.MouthScaling, featureScaleInfo.MouthScaling * featureScaleInfo.MouthStretchAmount));
        $("g[layerTypeId='9']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.MouthTranslateY + ")" + baseTransform[9].getScaleTransform(featureScaleInfo.MouthScaling, featureScaleInfo.MouthScaling * featureScaleInfo.MouthStretchAmount));
        //$("g[layerTypeId='10']").get(0).setAttribute("transform", "translate(0, " + featureScaleInfo.MouthTranslateY + ")" + baseTransform[9].getScaleTransform(featureScaleInfo.MouthScaling, featureScaleInfo.MouthScaling * featureScaleInfo.MouthStretchAmount));
    }

    function updateEyeTransform() {
        $("g[layerTypeId='30']").get(0).setAttribute("transform", "translate(" + -featureScaleInfo.EyeDistanceOffset + ", " + featureScaleInfo.EyeTranslateY + ")" + baseTransform[30].getScaleTransform(featureScaleInfo.EyeScaling * featureScaleInfo.EyeDisproportion, featureScaleInfo.EyeScaling * featureScaleInfo.EyeStretchAmount * featureScaleInfo.EyeDisproportion));
        $("g[layerTypeId='36']").get(0).setAttribute("transform", "translate(" + -featureScaleInfo.EyeDistanceOffset + ", " + featureScaleInfo.EyeTranslateY + ")" + baseTransform[36].getScaleTransform(featureScaleInfo.EyeScaling * featureScaleInfo.EyeDisproportion, featureScaleInfo.EyeScaling * featureScaleInfo.EyeStretchAmount * featureScaleInfo.EyeDisproportion));

        $("g[layerTypeId='31']").get(0).setAttribute("transform", "translate(" + featureScaleInfo.EyeDistanceOffset + ", " + featureScaleInfo.EyeTranslateY + ")" + baseTransform[31].getScaleTransform(featureScaleInfo.EyeScaling / featureScaleInfo.EyeDisproportion, featureScaleInfo.EyeScaling * featureScaleInfo.EyeStretchAmount / featureScaleInfo.EyeDisproportion));
        $("g[layerTypeId='37']").get(0).setAttribute("transform", "translate(" + featureScaleInfo.EyeDistanceOffset + ", " + featureScaleInfo.EyeTranslateY + ")" + baseTransform[37].getScaleTransform(featureScaleInfo.EyeScaling / featureScaleInfo.EyeDisproportion, featureScaleInfo.EyeScaling * featureScaleInfo.EyeStretchAmount / featureScaleInfo.EyeDisproportion));
    }

    function getMarkerPoint(feature, markerId) {
        if (feature == null) return null;

        for (var markerIndex in feature.Markers) {
            var marker = feature.Markers[markerIndex];
            if (marker.Id == markerId) {
                return marker;
            }
        }
        return null;
    }

    function setFeatureToPortrait(featureId) {
        var feature = downloadedFeatures[featureId]
        selectedFeatures[feature.FeatureTypeId] = feature;
        redrawPortrait();
    }

    function midPoint(point1, point2) {
        return new Point((point2.X - point1.X)/2 + point1.X, (point2.Y - point1.Y)/2 + point1.Y);
    }

    function scaleLayer(markerControlId1, markerControlId2, sourceFeatureId, sourceLayerIds) {
        var controlSource1 = getMarkerPoint(selectedFeatures[sourceFeatureId], markerControlId1);
        var controlSource2 = getMarkerPoint(selectedFeatures[sourceFeatureId], markerControlId2);
        var controlTarget1 = getMarkerPoint(selectedFeatures[4], markerControlId1);
        var controlTarget2 = getMarkerPoint(selectedFeatures[4], markerControlId2);

        if (controlSource1 == null || controlSource2 == null || controlTarget1 == null || controlTarget2 == null) return;

        var scaleFactor;
        if (controlSource2 != null && controlTarget2 != null) {
            var sourceDistance = Math.sqrt(Math.pow(controlSource1.Y - controlSource2.Y, 2)
                + Math.pow(controlSource1.X - controlSource2.X, 2));
            var targetDistance = Math.sqrt(Math.pow(controlTarget1.Y - controlTarget2.Y, 2)
                + Math.pow(controlTarget1.X - controlTarget2.X, 2));
            scaleFactor = targetDistance/sourceDistance;
        }
        var transformInfo = new TransformInfo(midPoint(controlSource1, controlSource2), midPoint(controlTarget1, controlTarget2), scaleFactor);

        for (var sourceLayerIdIndex in sourceLayerIds) {
            var sourceLayerId = sourceLayerIds[sourceLayerIdIndex];
            baseTransform[sourceLayerId] = transformInfo;
            var layerToTransform = $("g[layerTypeId='" + sourceLayerId + "']").get(0);
            if (layerToTransform != null)
                layerToTransform.setAttribute("transform", transformInfo.getBaseTransform());
        }
    }
    function addControlAreasToLayer(svg) {
        var leftEyeOuterMarker = getMarkerPoint(selectedFeatures[1], 26);
        var leftEyeInnerMarker = getMarkerPoint(selectedFeatures[1], 0);
        var eyeCenter = midPoint(leftEyeOuterMarker, leftEyeInnerMarker);
        var sourceDistance = Math.sqrt(Math.pow(leftEyeOuterMarker.Y - leftEyeInnerMarker.Y, 2)
            + Math.pow(leftEyeOuterMarker.X - leftEyeInnerMarker.X, 2)) / 2;

        var shape = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        shape.setAttribute("r", sourceDistance);
        shape.setAttribute("style", "fill:red;opacity:0;");
        shape.setAttribute("cx", eyeCenter.X);
        shape.setAttribute("cy", eyeCenter.Y);
        shape.setAttribute("onmouseover", "updateControlColor(true)");
        shape.setAttribute("onmouseout", "updateControlColor(false)");
        $("g[layerTypeId='30']", svg).append(shape);
    }

    function updateControlColor(display) {
        if (display) $("circle").attr("style", "fill:red;opacity:0.5");
        else $("circle").attr("style", "fill:red;opacity:0");
    }

    function redrawPortrait() {
        if (selectedFeatures[4] == null) {
            alert('Must select a head before selecting other features');
            return;
        }

        $("#PortraitSvg").empty();
        $("#PortraitSvg").append($("#feature" + selectedFeatures[4].Id + " svg").clone());
        var svg = $("#PortraitSvg svg");

        scaleLayer(0, 26, 1, [30,36]);
        scaleLayer(7, 28, 1, [31,37]);
        scaleLayer(32, 33, 2, [11,12,13]);
        scaleLayer(36, 37, 3, [6,9,10]);

        for (var featureIndex in selectedFeatures) {
            if (featureIndex == 4) continue;
            var feature = selectedFeatures[featureIndex];
            if (feature == null) continue;

            svg.append($("#feature" + feature.Id + " svg").children().clone());
        }

        addControlAreasToLayer(svg);
    }

    function addFeatureThumbnail(featureId) {
        $("#Features").append($('<div id="feature' + featureId + '" class="SelectableImage"></div>'));
        getFeature(featureId, function(feature) {displayFeature(feature, $("#feature" + featureId))});
        $("#feature" + featureId).click(function(){setFeatureToPortrait(featureId);});
    }

    $(function () {
        addFeatureThumbnail(2396);
        addFeatureThumbnail(2293);
        addFeatureThumbnail(2487);
        addFeatureThumbnail(2485);
        addFeatureThumbnail(2484);
    });
</script>

Jaw Height<div id="JawSlider" class="ValueSlider"></div>
Mouth Stretch<div id="MouthStretch" class="ValueSlider"></div>
Mouth Position<div id="MouthPosition" class="ValueSlider"></div>
Mouth Scaling<div id="MouthScaling" class="ValueSlider"></div>
Nose Stretch<div id="NoseStretch" class="ValueSlider"></div>
Nose Position<div id="NosePosition" class="ValueSlider"></div>
Nose Scaling<div id="NoseScaling" class="ValueSlider"></div>
Eye Stretch<div id="EyeStretch" class="ValueSlider"></div>
Eye Position<div id="EyePosition" class="ValueSlider"></div>
Eye Scaling<div id="EyeScaling" class="ValueSlider"></div>
Eye Distance<div id="EyeDistance" class="ValueSlider"></div>
Eye Disproportion<div id="EyeDisproportion" class="ValueSlider"></div>
<br />
<div class="ContentBorder CharacterImage">
    <div class="FullSizeImage" id="PortraitSvg"><svg/></div>
</div>
<div class="SelectableImageContainer" id="Features"/>